/*  File Name	: Monitor.h
 *  Author		: Javie Pong
 *	 E-mail		: 823960168@qq.com
 *  Created on	: 2011-9-1
 *  Description:
 */

#ifndef MONITOR_H_
#define MONITOR_H_

#include "Define.h"
#include "Reactor.h"
#include "MsgBlockPool.h"
#include "CommonStruct.h"
//#include "Task.h"
#include "Thread.h"
#include "Cmd.h"
#include "ComDefine.h"

#include <list>

class MonitorEx
{
public:
	MonitorEx();

	virtual ~MonitorEx();

	virtual int init(int list_size,int block_size,std::string pool_name);

	virtual void create_thread(int thr_num,void *cb_ptr,thread_cb_fun cb_fun,
			std::string thr_name,bool detached=true);

	virtual void create_request_thr(int thr_num,std::string thr_name,bool detached=true);

	virtual void create_respond_thr(int thr_num,std::string thr_name,bool detached=true);

	virtual int start(void);

	virtual int stop(void);

	virtual int request_mb_pop(MessageBlock *&mb);

	virtual int request_mb_push(MessageBlock *mb);

	virtual int respond_mb_pop(MessageBlock *&mb);

	virtual int respond_mb_push(MessageBlock *mb);

	static int request_loop(void *p);

	static int respond_loop(void *p);

	virtual int run_request_loop(void)=0;

	virtual int run_respond_loop(void)=0;

	Reactor *reactor(Reactor *reactor=NULL);

	void msg_pool_info(int block_size,std::string pool_name);

	MsgBlockPool *msg_pool(void);

	DuplexList *request_list(void) const;

	DuplexList *respond_list(void) const;

	virtual unsigned int svc_unique_id(void);

	virtual const int monitor_id(void);

	void wait_thread_exit(void);

	virtual void collection_info(void)=0;
protected:
	typedef std::list<Thread*> ThreadList;

	RT_MUTEX rt_mutex_;
	int svc_unique_id_;
	int block_size_;
	Reactor *reactor_;
	DuplexList *request_list_;
	DuplexList *respond_list_;
	ThreadList thread_list_;

	MsgBlockPool *msgblock_pool_;
	std::string pool_name_;
};

//////////////////////////////////////////////////////////////////////

template<class CService>
class Monitor:public MonitorEx
{
public:
	typedef ObjectPool<CService> ServicePool;
	typedef std::map<int,CService*>  ServiceMap;

public:
	Monitor();

	virtual ~Monitor();

	/**
	 * list_size	: the request_list,respond_list and log_list size
	 * block_size	: the MessageBlock size
	 * pool_size	: the MsgBlockPool size
	 * growth_size	: the MsgBlockPool growth size per times
	 * pool_name 	: the MsgBlockPool name
	 */
	virtual int init(int list_size,int block_size,int pool_size,
			int growth_size,std::string pool_name);

	void svc_pool_info(int pool_size,int growth_size);

	virtual ServicePool *svc_pool(void);

	virtual int handle_close(CService *svc);
	/**
	 * connecting service map
	 */
	ServiceMap &service_map(void);

	CService *find_service(int svc_id);

	int bind_service(CService *svc);

	int unbind_service(CService *svc);

	int unbind_all_service(void);

private:
	ServicePool *service_pool_;
	ServiceMap service_map_;
	RT_MUTEX rt_mutex_;

	int pool_size_;
	int growth_size_;
};


template<class CService>
Monitor<CService>::Monitor()
{
	this->service_pool_ = NULL;
	this->growth_size_ = 512;
	this->pool_size_ = 10240;
	this->service_map_.clear();
}

template<class CService>
Monitor<CService>::~Monitor()
{
	DELETE(this->service_pool_);
}

/**
 * list_size	: the request_list,respond_list and log_list size
 * block_size	: the MessageBlock size
 * pool_size	: the MsgBlockPool size
 * growth_size	: the MsgBlockPool growth size per times
 * pool_name 	: the MsgBlockPool name
 */
template<class CService>
int Monitor<CService>::init(int list_size,int block_size,int pool_size,
		int growth_size,std::string pool_name)
{
	this->svc_pool_info(pool_size,growth_size);
	return MonitorEx::init(list_size,block_size,pool_name);
}

template<class CService>
void Monitor<CService>::svc_pool_info(int pool_size,int growth_size)
{
	this->pool_size_ = pool_size;
	this->growth_size_ = growth_size;
}

template<class CService>
int Monitor<CService>::handle_close(CService *svc)
{
	this->unbind_service(svc);
	this->svc_pool()->push(svc);
	return 0;
}

/**
 * connecting service map
 */
template<class CService>
std::map<int,CService*> &Monitor<CService>::service_map(void)
{
	return this->service_map_;
}

template<class CService>
ObjectPool<CService> *Monitor<CService>::svc_pool(void)
{
	if(NULL==this->service_pool_)
	{
		CService s;
		this->service_pool_ = new ServicePool(pool_size_,growth_size_);
		this->service_pool_->set_pool_name(s.name());
	}
	return this->service_pool_;
}

template<class CService>
CService* Monitor<CService>::find_service(int svc_id)
{
	LockGuardReturn(RT_MUTEX,lock,this->rt_mutex_,NULL);
	typename ServiceMap::iterator iter
	= this->service_map_.find(svc_id);
	if(iter!=this->service_map_.end())
	{
		return iter->second;
	}
	return NULL;
}

template<class CService>
int Monitor<CService>::bind_service(CService *svc)
{
	if(NULL==svc)
	{
		return -1;
	}
	LockGuardReturn(RT_MUTEX,lock,this->rt_mutex_,-1);
	if (this->service_map_.find(svc->unique_id())
			!= this->service_map_.end())
	{
		return -1;
	}
	this->service_map_.insert(std::pair<int,CService*>(svc->unique_id(), svc));
	return 0;
}

template<class CService>
int Monitor<CService>::unbind_service(CService *svc)
{
	if(NULL==svc)
	{
		return -1;
	}
	LockGuardReturn(RT_MUTEX,lock,this->rt_mutex_,-1);
	typename ServiceMap::iterator iter  =
			this->service_map_.find(svc->unique_id());
	if(iter!=this->service_map_.end())
	{
		this->service_map_.erase(iter->first);
		return 0;
	}
	return 0;
}

template<class CService>
int Monitor<CService>::unbind_all_service(void)
{
	LockGuardReturn(RT_MUTEX,lock,this->rt_mutex_,-1);
	this->service_map_.clear();
	return 0;
}

#endif /* MONITOR_H_ */
